// sip_server.cpp
#include <iostream>
#include <cstring>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>

#define SIP_PORT 5060
#define BUF_SIZE 4096

std::string generate_response(const char* request, const std::string& status_code, const std::string& reason) {
    std::string via;
    const char* via_start = strstr(request, "Via: ");
    if (via_start) {
        via_start += 5;
        const char* via_end = strstr(via_start, "\r\n");
        via = std::string(via_start, via_end - via_start);
    }

    return "SIP/2.0 " + status_code + " " + reason + "\r\n"
           "Via: " + via + "\r\n"
           "From: <sip:bob@127.0.0.1>;tag=1234567\r\n"
           "To: <sip:alice@127.0.0.1>;tag=7654321\r\n"
           "Call-ID: call12345\r\n"
           "CSeq: 1 INVITE\r\n"
           "Content-Length: 0\r\n\r\n";
}

int main() {
    int sockfd;
    struct sockaddr_in server_addr, client_addr;
    char buffer[BUF_SIZE];
    socklen_t client_len = sizeof(client_addr);

    sockfd = socket(AF_INET, SOCK_DGRAM, 0);
    if (sockfd < 0) {
        std::cerr << "Socket creation failed!" << std::endl;
        return -1;
    }

    memset(&server_addr, 0, sizeof(server_addr));
    server_addr.sin_family = AF_INET;
    server_addr.sin_addr.s_addr = INADDR_ANY;
    server_addr.sin_port = htons(SIP_PORT);

    if (bind(sockfd, (struct sockaddr*)&server_addr, sizeof(server_addr)) < 0) {
        std::cerr << "Bind failed!" << std::endl;
        close(sockfd);
        return -1;
    }

    std::cout << "SIP server listening on port " << SIP_PORT << "..." << std::endl;

    while (true) {
        ssize_t recv_len = recvfrom(sockfd, buffer, BUF_SIZE, 0,
                                    (struct sockaddr*)&client_addr, &client_len);
        if (recv_len > 0) {
            buffer[recv_len] = '\0';
            std::cout << "Received SIP message:\n" << buffer << std::endl;

            std::string response = generate_response(buffer, "100", "Trying");
            sendto(sockfd, response.c_str(), response.size(), 0,
                   (struct sockaddr*)&client_addr, client_len);

            std::cout << "Sent SIP 100 Trying response." << std::endl;

            // Simulate 200 OK after some delay
            sleep(1);
            response = generate_response(buffer, "200", "OK");
            sendto(sockfd, response.c_str(), response.size(), 0,
                   (struct sockaddr*)&client_addr, client_len);

            std::cout << "Sent SIP 200 OK response." << std::endl;
        }
    }

    close(sockfd);
    return 0;
}